﻿@using ZR.CodeGenerator
@using ZR.Model.System.Generate
@using Infrastructure.Extensions;
@using ZR.Model.System.Model.Enums;
@* @model ZR.CodeGenerator.Model.GenerateDto; *@
@{
    var genTable = Model.GenTable;
    var genTableOptions=genTable.Options;
    var idFieldName = genTable.PkFieldName;
    List<GenTableColumn> listCols = genTable.ListItemColumns;
    List<GenTableColumn> editSetCols = genTable.EditActionSetValColumns;
    List<GenTableColumn> queryCols = genTable.QueryFormColumns;
    var entityClassName = genTable.EntityClassName;

    var genOptions = Model.GenOptions;
    var subTableOptions = Model.SubTableOptions;

    var replaceDto = Model.ReplaceDto;
    var dictHtml = new string[] { GenConstants.HTML_CHECKBOX, GenConstants.HTML_RADIO,GenConstants.HTML_RADIO_BTN, GenConstants.HTML_SELECT, GenConstants.HTML_SELECT_MULTI };
    var dicts = new List<GenTableColumn>();
    dicts.AddRange(Model.GenTable.Columns.FindAll((Predicate<GenTableColumn>)(f => dictHtml.Contains(f.HtmlType))));
    if (Model.GenTable.SubTable != null && Model.GenTable.SubTableName.IsNotEmpty())
    {
        dicts.AddRange(Model.GenTable?.SubTable?.Columns?.FindAll((Predicate<GenTableColumn>)(f => dictHtml.Contains(f.HtmlType))));
    }
    int index = 0;
}
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using System.Linq.Expressions;
using Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Infrastructure.Filters;
using Mapster;
using @(genOptions.RepositoriesNamespace);
using @(genOptions.IServicsNamespace).@(genOptions.SubNamespace).IService;
using @(genOptions.DtosNamespace).@(genOptions.SubNamespace).Dto;
using @(genOptions.DtosNamespace).@(genOptions.SubNamespace).Entity;
using @(genOptions.ModelsNamespace).Enums;
@if(genTable.TplCategory == "tree")
{
@:using System.Collections.Generic;
}

namespace @(genOptions.ServicesNamespace).@(genOptions.SubNamespace).Service
{

    /// <summary>
    /// @(genTable.FunctionName)服务基类
    /// </summary>
    public class @(genTable.FunctionCode)ServiceBase : BaseService<@(entityClassName)>
    {
    @if(genTableOptions.IsTreeTable && !string.IsNullOrWhiteSpace(genTableOptions.TreeTableNodePathField))
    {
            @:private async Task Set@(genTableOptions.TreeTableNodePathField)(@(entityClassName) model)
            @:{
                    @:var paIdPath= await this.Repository.Context.Queryable<@(entityClassName)>()
                                    @:.Where(m => m.@(idFieldName) == model.@(genTableOptions.TreeTableNodePaIdField))
                                    @:.Select(m => m.@(genTableOptions.TreeTableNodePathField)).FirstAsync()??"/0/";
                    @:model.@(genTableOptions.TreeTableNodePathField) = $"{paIdPath}{model.@(idFieldName)}/";
            @:}
    }

    @if (replaceDto.ShowBtnAdd)
    {
            @:/// <summary>
            @:/// 添加@(genTable.FunctionName)
            @:/// </summary>
            @:/// <param name="model"></param>
            @:/// <returns></returns>
            @:public virtual async Task<bool> Add@(genTable.FunctionCode)(@(entityClassName) model)
            @:{
                 @if(genTableOptions.IsTreeTable && !string.IsNullOrWhiteSpace(genTableOptions.TreeTableNodePathField))
                 {
                    @:await Set@(genTableOptions.TreeTableNodePathField)(model);
                 }
                    @:return await Insertable(model).ExecuteCommandIdentityIntoEntityAsync();
            @:}
    }

    @if(replaceDto.ShowBtnEdit)
    {
            @:/// <summary>
            @:/// 修改@(genTable.FunctionName)
            @:/// </summary>
            @:/// <param name="model"></param>
            @:/// <returns></returns>
            @:public virtual async Task<bool> Modify@(genTable.FunctionCode)(@(entityClassName) model)
            @:{
                @if(genTableOptions.IsTreeTable && !string.IsNullOrWhiteSpace(genTableOptions.TreeTableNodePathField))
                {
                    @:await Set@(genTableOptions.TreeTableNodePathField)(model);
                }
                    @:Expression<Func<@(entityClassName), object>> upColsExpr = m => new
                    @:{
                    @foreach(var item in editSetCols)
                    {
                            @:m.@(item.CsharpField),
                    }
                    @:};
                    @:return await UpdateAsync(model, upColsExpr);
            @:}
    }

    @if (replaceDto.ShowBtnDelete || replaceDto.ShowBtnMultiDel)
    {
            @:/// <summary>
            @:/// 删除@(genTable.FunctionName)
            @:/// </summary>
            @:/// <param name="ids"></param>
            @:/// <param name="isRealDel"></param>
            @:/// <returns></returns>
            @:public virtual async Task<bool> Delete@(genTable.FunctionCode)(long[] ids, bool isRealDel = true)
            @:{
                    @:var isOk = false;
                    @:if (isRealDel)
                    @:{
                            @:isOk = await Deleteable().Where(m => ids.Contains(m.@(idFieldName))).ExecuteCommandHasChangeAsync();
                    @:}
            @if(genTableOptions.IsEnableFDel)
            {
                    @:else
                    @:{
                            @:isOk = await Updateable().SetColumns(m => new @(entityClassName)
                            @:{
                                    @:@(genTableOptions.StateCodeField) = DataStateEnum.Deleted.ToEnumCode(),
                                @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifierField))
                                {
                                    @:@(genTableOptions.ModifierField) = App.HttpContext.GetName(),
                                }
                                @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifierIdField))
                                {
                                    @:@(genTableOptions.ModifierIdField) = App.HttpContext.GetUId(),
                                }
                                @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifyTimeField))
                                {
                                    @:@(genTableOptions.ModifyTimeField) = DateTime.Now,
                                }
                            @:})
                            @:.Where(m => ids.Contains(m.@(idFieldName)))
                            @:.ExecuteCommandHasChangeAsync();
                    @:}
            }
                    @:return isOk;
            @:}
    }

    @if(genTableOptions.IsEnableStateChange)
    {
            @:/// <summary>
            @:/// 变更@(genTable.FunctionName)状态
            @:/// </summary>
            @:/// <param name="req"></param>
            @:/// <returns></returns>
            @:public virtual async Task<bool> Change@(genTable.FunctionCode)State([FromBody] Change@(genTable.FunctionCode)StateReq req)
            @:{
                    @:var stateEnum = req.StateEnum;
                    @:if (stateEnum == null)
                    @:{
                            @:throw new CustomException(ResultCode.PARAM_ERROR);
                    @:}
                    @:var isOk = await Updateable().SetColumns(m => new @(entityClassName)
                    @:{
                            @:@(genTableOptions.StateCodeField) = stateEnum.ToEnumCode(),
                        @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifierField))
                        {
                            @:@(genTableOptions.ModifierField) = App.HttpContext.GetName(),
                        }
                        @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifierIdField))
                        {
                            @:@(genTableOptions.ModifierIdField) = App.HttpContext.GetUId(),
                        }
                        @if(!string.IsNullOrWhiteSpace(genTableOptions.ModifyTimeField))
                        {
                            @:@(genTableOptions.ModifyTimeField) = DateTime.Now,
                        }
                    @:})
                    @:.Where(m => m.@(idFieldName) == req.Id)
                    @:.ExecuteCommandHasChangeAsync();
                    @:return isOk;
            @:}
    }

    @if(genTableOptions.IsTreeTable)
    {
            index=0;
            @:/// <summary>
            @:/// 获取@(genTable.FunctionName)树选择列表
            @:/// </summary>
            @:/// <param name="req"></param>
            @:/// <returns></returns>
            @:public virtual async Task<List<TreeNodeInfo>> Get@(genTable.FunctionCode)TreeSelectList(Get@(genTable.FunctionCode)TreeSelectListReq req)
            @:{
                    @:var list=await Repository
                    @if(genTableOptions.KeywordsMatchFileds?.Count()>0)
                    {
                            @:.WhereIF(!string.IsNullOrWhiteSpace(req.Keywords), m => 
                        @foreach(var item in genTableOptions.KeywordsMatchFileds)
                        {
                            index++;
                                @:@(index>1?"|| ":"")m.@(item).Contains(req.Keywords)
                        }
                            @:)
                    }
                            @:.WhereIF(req.OnlyLevel1Node,m=>m.@(genTableOptions.TreeTableNodePaIdField)==0)
                    @if(!string.IsNullOrEmpty(genTableOptions.StateCodeField))
                    {
                            @:.Where(m=>m.@(genTableOptions.StateCodeField)!=DataStateEnum.Deleted.ToEnumCode())
                    }
                            @:.Select(m => new TreeNodeInfo
                            @:{
                                    @:Id = m.@(genTableOptions.TreeTableNodeIdField).ToString(),
                                    @:PaId = m.@(genTableOptions.TreeTableNodePaIdField).ToString(),
                                    @:Label=m.@(genTableOptions.TreeTableNodeNameField)
                            @:})
                            @:.ToListAsync();
                    @:if (req.IsReturnRoot)
                    @:{
                            @:list.Add(new TreeNodeInfo
                            @:{
                                    @:Id = "0",
                                    @:Label = string.IsNullOrWhiteSpace(req.RootNodeName)?"所有@(genTable.FunctionName)":req.RootNodeName,
                                    @:PaId = "-1"
                            @:});
                    @:}
                    @:var treeList=BuildTree(list);
                    @:return treeList;
            @:}
    }
            /// <summary>
            /// 获取@(genTable.FunctionName)分页列表
            /// </summary>
            /// <param name="req"></param>
            /// <returns></returns>
            public virtual async Task<PagedInfo<@(genTable.FunctionCode)ListItemDto>> Get@(genTable.FunctionCode)PageList(Get@(genTable.FunctionCode)PageListReq req)
            {
                @if(genTableOptions.IsShowLeftTree)
                {
                    @:string pathStr=null;
                    @:if(req.TreeNodeId>=0)
                    @:{
                            @:pathStr= $"/{req.TreeNodeId}/";
                    @:}
                }
                    var filterExp=PageListFilterExp(req);
                
                @if(genTableOptions.IsShowLeftTree && !string.IsNullOrEmpty(genTableOptions.LeftTreeTableEntityName))
                {
                    @:var result = await Repository.Context.Queryable<@(entityClassName)>()
                                @:.InnerJoin<@(genTableOptions.LeftTreeTableEntityName)>((m,n)=>m.@(genTableOptions.LeftTreeNodeIdField)==n.@(genTableOptions.LeftTreeNodeIdField))
                    if(genTableOptions.IsTreeTable)
                    {
                                @:.LeftJoin<@(entityClassName)>((m,n,o)=>m.@(genTableOptions.TreeTableNodePaIdField)==o.@(genTableOptions.TreeTableNodeIdField))
                    }
                    else
                    {   
                        if(genTableOptions.LeftTreeComponent=="company_depart")
                        {
                                @:.InnerJoin<CompanyEntity>((m,n,o)=>n.CompanyId==o.CompanyId)
                        }
                    }
                }
                else if(genTableOptions.IsTreeTable)
                {
                    @:var result = await Repository.Context.Queryable<@(entityClassName)>()
                                @:.LeftJoin<@(entityClassName)>((m,n)=>m.@(genTableOptions.TreeTableNodePaIdField)==n.@(genTableOptions.TreeTableNodeIdField))
                }
                else
                {
                    @:var result = await Repository.Context.Queryable<@(entityClassName)>()
                }
                                .Where(filterExp.ToExpression())
                    @if(genTableOptions.IsShowLeftTree)
                    {
                        string bindField;
                        if(genTableOptions.IsTreeTable)
                        {
                            bindField = genTableOptions.TreeTableNodePaIdField;
                        }
                        else
                        {
                            bindField = genTableOptions.LeftTreeNodeIdField;
                        }
                        if (!string.IsNullOrEmpty(genTableOptions.LeftTreeNodePathField))
                        {
                                if(genTableOptions.IsTreeTable)
                                {
                                @:.WhereIF(req.TreeNodeId>=0 && !req.IsDefaultNodeType,(m,n)=>n.@(genTableOptions.LeftTreeNodePathField).Contains(pathStr))
                                }
                                else
                                {
                                    if(genTableOptions.LeftTreeComponent=="company_depart")
                                    {
                                @:.WhereIF(req.TreeNodeId>=0 && !req.IsDefaultNodeType,(m,n,o)=>o.CompanyIdPath.Contains(pathStr))
                                @:.WhereIF(req.TreeNodeId>=0 && req.IsDefaultNodeType,(m,n)=>n.@(genTableOptions.LeftTreeNodePathField).Contains(pathStr))
                                    }
                                }
                                if(!string.IsNullOrEmpty(genTableOptions.TreeTableNodePathField))
                                {
                                @:.WhereIF(req.TreeNodeId>=0 && req.IsDefaultNodeType,(m,n)=>m.@(genTableOptions.TreeTableNodePathField).Contains(pathStr))
                                }
                        }
                        else
                        {
                            if (!string.IsNullOrEmpty(genTableOptions.TreeTableNodePathField))
                            {
                                @:.WhereIF(req.TreeNodeId>=0,(m,n)=>m.@(genTableOptions.TreeTableNodePathField).Contains(pathStr))
                            }
                            else
                            {
                                @:.WhereIF(req.TreeNodeId>=0,m=>m.@(bindField)==req.TreeNodeId)
                            }
                        }
                    }
                    @if (genTableOptions.ListKeywordsFields?.Count() > 0)
                    {
                        index = 0;
                                @:.WhereIF(!string.IsNullOrEmpty(req.Keywords), 
                                    @:m => 
                        @foreach (var item in genTableOptions.ListKeywordsFields)
                        {
                            index++;
                                        @:@(index > 1 ? "|| " : "")m.@(item).Contains(req.Keywords)
                        }
                                @:)
                    }
                    @if(!string.IsNullOrEmpty(genTableOptions.StateCodeField))
                    {
                                @:.Where(m=>m.@(genTableOptions.StateCodeField)!=DataStateEnum.Deleted.ToEnumCode())
                    }
                    @if(!string.IsNullOrEmpty(genTableOptions.SortField))
                    {
                                @:.OrderBy(m=>m.@(genTableOptions.SortField),@(genTableOptions.SortType=="asc"?"OrderByType.Asc":"OrderByType.Desc"))
                    }
                    
                    @if(genTableOptions.IsShowLeftTree && !string.IsNullOrEmpty(genTableOptions.LeftTreeTableEntityName))
                    {
                                @:.Select((m,n@(genTableOptions.IsTreeTable?",o":""))=>new @(genTable.FunctionCode)ListItemDto
                                @:{
                            @foreach(var item in listCols)
                            {
                                            @:@item.CsharpField=m.@item.CsharpField,
                                        if(genTableOptions.IsShowLeftTree && item.CsharpField==genTableOptions.LeftTreeNodeIdField)
                                        {
                                            @:Belong@(genTableOptions.LeftTreeNodeNameField)=n.@(genTableOptions.LeftTreeNodeNameField),
                                        }
                                        if(genTableOptions.IsTreeTable && genTableOptions.TreeTableNodePaIdField==item.CsharpField)
                                        {
                                            @:Pa@(genTableOptions.TreeTableNodeNameField)=o.@(genTableOptions.TreeTableNodeNameField),
                                        }
                            }
                                @:})
                    }
                    else @if(genTableOptions.IsTreeTable)
                    {
                                @:.Select((m,n)=>new @(genTable.FunctionCode)ListItemDto
                                @:{
                        @foreach(var item in listCols)
                        {
                                        @:@item.CsharpField=m.@item.CsharpField,
                            if(genTableOptions.IsTreeTable && genTableOptions.TreeTableNodePaIdField==item.CsharpField)
                            {
                                        @:Pa@(genTableOptions.TreeTableNodeNameField)=n.@(genTableOptions.TreeTableNodeNameField),
                            }

                        }
                                @:})
                    }
                    else
                    {
                                @:.Select(m=>new @(genTable.FunctionCode)ListItemDto
                                @:{
                            @foreach(var item in listCols)
                            {
                                            @:@item.CsharpField=m.@item.CsharpField,
                            }
                                @:})
                    }
                    .ToPageAsync(req);
                    return result;
        }

        /// <summary>
        /// 分页列表过滤表达式
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        private static Expressionable<@(entityClassName)> PageListFilterExp(Get@(genTable.FunctionCode)PageListReq req)
        {
                var predicate = Expressionable.Create<@(entityClassName)>();

@foreach(var column in queryCols)
{
        @if(column.HtmlType == "selectMulti")
        {
                @:predicate = predicate.AndIF(req.@(column.CsharpField) != null, m => req.@(column.CsharpField).Contains(m.@(column.CsharpField)));
        }
        else if(column.CsharpType == "string")
        {
                @:predicate = predicate.AndIF(!string.IsNullOrEmpty(req.@(column.CsharpField)), @(CodeGeneratorTool.QueryExp(column.CsharpField, column.QueryType));
        }
        else if(column.CsharpType == "DateTime")
        {
            if(column.HtmlType == "month")
            {
                @:DateTime monthEnd = Convert.ToDateTime(req.@(column.CsharpField)).AddMonths(1);
                @:predicate = predicate.AndIF(req.@(column.CsharpField) != null, m => m.@(column.CsharpField) >= req.@(column.CsharpField) && m.@(column.CsharpField) < monthEnd);
            }
            else
            {
                @:predicate = predicate.AndIF(req.Begin@(column.CsharpField) != null, m => m.@(column.CsharpField) >= req.Begin@(column.CsharpField));
                @:predicate = predicate.AndIF(req.End@(column.CsharpField) != null, m => m.@(column.CsharpField) <= req.End@(column.CsharpField));
            }
        }
        else if(column.CsharpType == "int" || column.CsharpType == "long")
        {
                @:predicate = predicate.AndIF(req.@(column.CsharpField) != null, @(CodeGeneratorTool.QueryExp(column.CsharpField, column.QueryType));
        }
}
                return predicate;
        }

        /// <summary>
        /// 获取@(genTable.FunctionName)详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual async Task<@(genTable.FunctionCode)DetailDto> Get@(genTable.FunctionCode)Detail(long id)
        {
                var detail = await Queryable()
                    .Where(x => x.@(idFieldName) == id)
                    .FirstAsync();
                var result = detail.Adapt<@(genTable.FunctionCode)DetailDto>();
                return result;
        }

    }
}